package com.qinglei.recoup.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qinglei.recoup.common.domain.CommonConstant;
import com.qinglei.recoup.common.exception.RedisConnectException;
import com.qinglei.recoup.common.service.RedisService;
import com.qinglei.recoup.common.utils.JsonUtils;
import com.qinglei.recoup.hmp.pojo.event.SendMpAlarmInfoEvent;
import com.qinglei.recoup.system.dao.BedHealthStateMapper;
import com.qinglei.recoup.system.domain.*;
import com.qinglei.recoup.system.dao.BedHealthBreathDailyDataMapper;
import com.qinglei.recoup.system.enums.EventEnum;
import com.qinglei.recoup.system.pojo.BedMonitorTimeVO;
import com.qinglei.recoup.system.pojo.BedStatusVO;
import com.qinglei.recoup.system.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qinglei.recoup.third.event.AlarmInfoEvent;
import com.qinglei.recoup.third.properties.FuXingProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;


import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.List;

/**
 * @author dqh
 */
@Service
@Slf4j
public class BedHealthBreathDailyDataServiceImpl extends ServiceImpl<BedHealthBreathDailyDataMapper, BedHealthBreathDailyData> implements BedHealthBreathDailyDataService {

    @Autowired
    private EventLogService eventLogService;
    @Autowired
    private EventWsService eventWsService;
    @Autowired
    private BedService bedService;

    @Autowired
    private EventService eventService;

    @Autowired
    private RedisService redisService;

    @Resource
    private BedHealthStateMapper bedHealthStateMapper;

    @Resource
    private EventProcService eventProcService;

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private BuildingService buildingService;


    @Autowired
    private EventLogTestService eventLogTestService;

    @Autowired
    private ApplicationContext applicationContext;

    @Resource
    private FuXingProperties fuXingProperties;

    @Override
    public BedHealthBreathDailyData getHealthReport(HealthSearchQO healthSearchQO) {
        return this.baseMapper.getHealthReport(healthSearchQO);
    }

    @Override
    public void breathBpmHight(String bedId) {
            Bed bed = bedService.getBaseMapper().selectById(bedId);
            try {
                //删除呼吸正常数据队列
                redisService.del(CommonConstant.BREATH_BPM_NOMAL+bed.getId());
                //删除呼吸BPM最高数据队列
                redisService.del(CommonConstant.BREATH_BPM_HIGHT_TIME_START+"-"+bedId);
                processingData(bed,BedHealthState.SUB_STATUS_BREATH_HIGHT,EventEnum.ALARM_BREATH_BPM_HIGH.getCode(),EventEnum.ALARM_BREATH_BPM_HIGH.getContent());
            } catch (RedisConnectException redisConnectException) {
                redisConnectException.printStackTrace();
            }

    }

    @Override
    public void breathBpmLow(String bedId) {
            Bed bed = bedService.getBaseMapper().selectById(bedId);
            try {
                redisService.del(CommonConstant.BREATH_BPM_NOMAL+bed.getId());
                redisService.del(CommonConstant.BREATH_BPM_LOW_TIME_START+"-"+bedId);
                processingData(bed,BedHealthState.SUB_STATUS_BREATH_LOW,EventEnum.ALARM_BREATH_BPM_LOW.getCode(),EventEnum.ALARM_BREATH_BPM_LOW.getContent());
            } catch (RedisConnectException redisConnectException) {
                redisConnectException.printStackTrace();
            }
    }

    @Override
    public void heartBpmHight(String bedId) {
            Bed bed = bedService.getBaseMapper().selectById(bedId);
            try {
                redisService.del(CommonConstant.HEART_BPM_NOMAL+bed.getId());
                redisService.del(CommonConstant.HEART_BPM_HIGHT_TIME_START+"-"+bedId);
                processingData(bed,BedHealthState.SUB_STATUS_HEART_HIGHT,EventEnum.ALARM_HEART_BPM_HIGH.getCode(),EventEnum.ALARM_HEART_BPM_HIGH.getContent());
            } catch (RedisConnectException redisConnectException) {
                redisConnectException.printStackTrace();
            }

    }

    @Override
    public void heartBpmLow(String bedId) {
            Bed bed = bedService.getBaseMapper().selectById(bedId);
            try {
                redisService.del(CommonConstant.HEART_BPM_NOMAL+bed.getId());
                redisService.del(CommonConstant.HEART_BPM_LOW_TIME_START+"-"+bedId);
                processingData(bed,BedHealthState.SUB_STATUS_HEART_LOW,EventEnum.ALARM_HEART_BPM_LOW.getCode(),EventEnum.ALARM_HEART_BPM_LOW.getContent());
            } catch (RedisConnectException redisConnectException) {
                redisConnectException.printStackTrace();
            }

    }



    /**
     * 处理
     * @param bed
     * @param bpmType
     * @param SubStatus
     * @param statusName
     */
    @Override
    public synchronized void processingData(Bed bed,Integer bpmType,Integer SubStatus,String statusName){
        if (bed == null) {
            log.debug("procRadarData not bind bed sn: {}", bed.getName());
            return;
        }
        // 监测仪关闭状态不处理监测仪数据
        if (bed.getIsRadarOn() == Bed.RADAR_OFF) {
            log.info("procUserData radar off bedId: {}", bed.getId());
            return;
        }
        if(bed.getStatus() == Bed.STATUS_ALARM){
            log.info("bed is  alarm", bed.getId());
            return;
        }
        QueryWrapper queryWrapperBedHealthState = new QueryWrapper();
        queryWrapperBedHealthState.eq("bed_id",bed.getId());
        //queryWrapperBedHealthState.eq("type",SubStatus);
        List<BedHealthState> bedHealthStateOld = bedHealthStateMapper.selectList(queryWrapperBedHealthState);
        if(bedHealthStateOld!=null && bedHealthStateOld.size()>0){
            log.info("bed is  alarm", bed.getId());
            return;
        }

        //更新床位消息
        BedHealthState bedHealthStateNew = new BedHealthState();
        bedHealthStateNew.setBedId(bed.getId());
        bedHealthStateNew.setType(bpmType);
        bedHealthStateMapper.insert(bedHealthStateNew);

//        EventLog eventlog = eventLogService.getLastEvent(bed.getId());
//
//        if(eventlog!=null && eventlog.getType().equals(SubStatus)){
//            log.info("bed is  alarm", bed.getId());
//            return;
//        }

        //保存事件
        Event event = new Event();
        event.setType(bpmType);
        event.setBedId(bed.getId());
        event.setContent(statusName);
        event.setTenantId(bed.getTenantId());
        event.setHappenTime(LocalDateTime.now());
        eventService.save(event);

        //更新床位信息
        Bed bedUpdate = new Bed();
        bedUpdate.setId(bed.getId());
        bedUpdate.setEventId(event.getId());
        //bedUpdate.setStatus(Bed.STATUS_ALARM);
        bedService.saveOrUpdate(bedUpdate);


        EventProc eventProc = new EventProc();
        eventProc.setTenantId(bed.getTenantId());
        eventProc.setStatus(EventProc.STATUS_HAPPEN);
        eventProc.setBedId(bed.getId());
        eventProc.setHappenTime(event.getHappenTime());
        eventProc.setEventId(event.getId());
        eventProcService.save(eventProc);


//        //给前端推送消息
        Building building = buildingService.getById(bed.getBuildingId());
        BedStatusVO bedStatusVO = new BedStatusVO();
        bedStatusVO.setBedId(bed.getId());
        bedStatusVO.setBedName(getBedName(bed.getId()));
        if(building!=null){
            bedStatusVO.setBuildingName(building.getName());
        }
        bedStatusVO.setStatus(bed.getStatus());
        bedStatusVO.setStatusName(getStatusName(bed.getStatus(),bed.getSubStatus()));
        bedStatusVO.setSubStatus(bed.getSubStatus());
        bedStatusVO.setHealthyBpm(bpmType);//类型
        bedStatusVO.setHealthyStatusName(statusName);//名称
        bedStatusVO.setEventId(event.getId());
        bedStatusVO.setRadarType(1);
        BedMonitorTimeVO bedMonitorTimeVO = bedService.getBedCurMonitorTime(bed.getId());
        if(bedMonitorTimeVO!=null){
            bedStatusVO.setCurMonitorTime(bedMonitorTimeVO.getStartTime() + '-' + bedMonitorTimeVO.getEndTime());
        }
        eventWsService.pushBedStatusMsg(bedStatusVO);




        //推送日志消息
        EventLog eventLog = new EventLog();
        eventLog.setBedId(bed.getId());
        eventLog.setEventId(event.getId());
        eventLog.setContent(statusName);
        eventLog.setTenantId(bed.getTenantId());
        eventLog.setCreateTime(LocalDateTime.now());
        eventLog.setType(SubStatus);
        eventLog.setName(getBedName(bed.getId()));
        eventLog.setTypeGroup(EventEnum.TYPE_ALARM);
        eventWsService.pushEventMsg(eventLog);
        eventLogService.save(eventLog);

        // 推送警报模板消息
        SendMpAlarmInfoEvent sendMpAlarmInfoEvent = new SendMpAlarmInfoEvent(this.applicationContext);
        sendMpAlarmInfoEvent.setEventId(event.getId());
        applicationContext.publishEvent(sendMpAlarmInfoEvent);
        log.info("processingData send alarm event:{}", sendMpAlarmInfoEvent);

        // 复星报警信息推送
        if (event.getTenantId() == fuXingProperties.getTenantId()) {
            AlarmInfoEvent alarmInfoEvent = new AlarmInfoEvent(this.applicationContext);
            alarmInfoEvent.setEventId(event.getId());
            applicationContext.publishEvent(alarmInfoEvent);
            log.info("processingData send fuxing alarm event: {}", alarmInfoEvent);
        }
    }

    @Override
    @Transactional
    public  void processingDataRecovery(Bed bed,Integer bpmType,Integer SubStatus,String statusName){
        if (bed == null) {
            log.debug("procRadarData not bind bed sn: {}", bed.getName());
            return;
        }
        // 监测仪关闭状态不处理监测仪数据
        if (bed.getIsRadarOn() == Bed.RADAR_OFF) {
            log.info("procUserData radar off bedId: {}", bed.getId());
            return;
        }
        if(bed.getStatus() == Bed.STATUS_ALARM){
            log.info("bed is  alarm", bed.getId());
            return;
        }


        //保存事件
        //Event event = eventService.getById(bed.getHealthEventId());
        Event event = eventService.getById(bed.getEventId());

        //给前端推送消息
        Building building = buildingService.getById(bed.getBuildingId());
        BedStatusVO bedStatusVO = bedService.getBedStatusById(bed.getId());
        bedStatusVO.setMissedEventNum(bedStatusVO.getMissedEventNum()+1);
        bedStatusVO.setBedName(getBedName(bed.getId()));
        if(building!=null){
            bedStatusVO.setBuildingName(building.getName());
        }
        bedStatusVO.setStatus(bed.getStatus());
        bedStatusVO.setStatusName(getStatusName(bed.getStatus(),bed.getSubStatus()));
        bedStatusVO.setSubStatus(bed.getSubStatus());
        bedStatusVO.setHealthyBpm(bpmType);//类型
        bedStatusVO.setHealthyStatusName(statusName);//名称
        bedStatusVO.setEventId(event.getId());
        bedStatusVO.setRadarType(1);
        BedMonitorTimeVO bedMonitorTimeVO = bedService.getBedCurMonitorTime(bed.getId());
        if(bedMonitorTimeVO!=null){
            bedStatusVO.setCurMonitorTime(bedMonitorTimeVO.getStartTime() + '-' + bedMonitorTimeVO.getEndTime());
        }
        eventWsService.pushBedStatusMsg(bedStatusVO);


        //推送日志消息
        EventLog eventLog = new EventLog();
        eventLog.setBedId(bed.getId());
        eventLog.setEventId(event.getId());
        eventLog.setContent(statusName);
        eventLog.setTenantId(bed.getTenantId());
        eventLog.setCreateTime(LocalDateTime.now());
        eventLog.setType(SubStatus);
        eventLog.setName(getBedName(bed.getId()));
        eventLog.setTypeGroup(EventEnum.TYPE_MONITOR_TIME);
        eventWsService.pushEventMsg(eventLog);
        eventLogService.save(eventLog);

//        EventLogTest eventLogTest = new EventLogTest();
//        eventLogTest.setBedId(bed.getId());
//        eventLogTest.setEventId(event.getId());
//        eventLogTest.setContent(statusName);
//        eventLogTest.setTenantId(bed.getTenantId());
//        eventLogTest.setCreateTime(LocalDateTime.now());
//        eventLogTest.setType(SubStatus);
//        eventLogTest.setName(getBedName(bed.getId()));
//        eventLogTest.setTypeGroup(1);
//        eventLogTestService.save(eventLogTest);


//        //保存遗漏事件
        eventProcService.saveMissedEvent(event.getId());
        //更新床位消息
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("bed_id",bed.getId());
        bedHealthStateMapper.delete(queryWrapper);

    }


    /**
     * 添加待接单事件到缓冲
     *
     * @param eventBedBO
     */
    private void addWaitTakeEventCache(EventBedBO eventBedBO) {
        try {
            Integer timeout = systemConfigService.getTakeEventTimeoutRedisCache(eventBedBO.getTenantId());
            long score = timeout + System.currentTimeMillis() / 1000;
            redisService.zadd(CommonConstant.WAIT_TAKE_EVENT_ZSET_PREFIX,
                    (double) score, JsonUtils.objectToJson(eventBedBO));
        } catch (Exception e) {
            log.error("addWaitTakeEventCache error eventBedBO:{}", eventBedBO, e);
        }
    }
    private String getBedName(Integer bedId) {
        BedBO bedFullName = bedService.getBedFullName(bedId);
        String name = "";
        if (bedFullName != null) {
            name =bedFullName.getBuildingName()+"-"+ bedFullName.getFloorName() + "-" + bedFullName.getRoomName()
                    + "-" + bedFullName.getBedName();
        }
        return name;
    }

    private  String getStatusName(Integer status,Integer SubStatus){
        String resultStr = new String();
        if(status==1){
            switch(SubStatus){
                case 1 :
                    resultStr = "离床";
                    break; //可选
                case 2 :
                    //resultStr = "清醒";
                    resultStr = "在床";
                    break; //可选
                case 3 :
                    //resultStr = "浅睡";
                    resultStr = "在床";
                    break; //可选
                case 4 :
                   // resultStr = "深睡";
                    resultStr = "在床";
                    break; //可选
                case 5 :
                    resultStr = "无人";
                    break; //可选
                case 6 :
                    resultStr = "有人";
                    break; //可选
                default : //可选
                    //语句
            }
        }else if(status==2){
            switch(SubStatus){
                case 1 :
                    resultStr = "离床";
                    break; //可选
                case 2 :
                    resultStr = "跌倒";
                    break; //可选
                default : //可选
                    //语句
            }
        }

        return  resultStr;
    }
}
